package dp.gr03.payroll.affiliations;

import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map.Entry;

import dp.gr03.payroll.Date;
import dp.gr03.payroll.Paycheck;
import dp.gr03.payroll.payrollDomain.Affiliation;

public class UnionAffiliation implements Affiliation
{
    protected int memberId;
    protected double dues;
    protected HashMap<GregorianCalendar, ServiceCharge> serviceCharges;

    public UnionAffiliation(int memberId, double dues)
    {
        this.memberId = memberId;
        this.dues = dues;
        serviceCharges = new HashMap<GregorianCalendar, ServiceCharge>();
    }

    @Override
    public double getFee()
    {
        return dues;
    }

    public int getMemberId()
    {
        return memberId;
    }

    public double getDues()
    {
        return dues;
    }

    public ServiceCharge getServiceCharge(GregorianCalendar date)
    {
        return serviceCharges.get(date);
    }

    public void addServiceCharge(GregorianCalendar date, ServiceCharge sc)
    {
        serviceCharges.put(date, sc);
    }

    public int numberOfFriddaysInPayPeriod(GregorianCalendar payPeriodStart, GregorianCalendar payPeriodEnd)
    {
        int fridays = 0;
        GregorianCalendar calculateDate = (GregorianCalendar) payPeriodStart.clone();
        while (calculateDate.getTimeInMillis() <= payPeriodEnd.getTimeInMillis())
        {
            if (calculateDate.get(GregorianCalendar.DAY_OF_WEEK) == GregorianCalendar.FRIDAY)
                fridays++;
            calculateDate.add(GregorianCalendar.DAY_OF_MONTH, 1);
        }
        return fridays;
    }

    public double calculateDeductions(Paycheck pc)
    {
        int fridays = numberOfFriddaysInPayPeriod(pc.getPayPeriodStartDate(), pc.getPayPeriodEndDate());
        return dues * fridays;
    }

    @Override
    public double calculatePay(Paycheck pc)
    {
        double pay = calculateDeductions(pc);
        pay += calculateServiceChargers(pc);
        return pay;
    }

    private double calculateServiceChargers(Paycheck pc)
    {
        double serviceAmmount = 0;
        for (Entry<GregorianCalendar, ServiceCharge> entry : serviceCharges.entrySet())
        {
            if (Date.isInPayPeriod(entry.getKey(), pc))
                serviceAmmount += entry.getValue().getAmount();
        }
        return serviceAmmount;
    }
}
